還記得 Day 08 的樂高案例劇情嗎?當有人將一個樂高手冊的基礎版本,分享出來,有兩個網友同時基於這個基礎版本,各自實作自己的手冊。現在 A 網友發現 B 網友延伸製作的部分很不錯,但又想要保留自己目前已經做的內容,那該怎麼做?「合併」應該是必然的解決方案,把 B 網友製作的部分,跟 A 網友製作的部分合併在一起,就可以兩個願望一次滿足了。
git merge
在 GIT 官方的手冊中,是這樣描述 git merge
這個指令的:
Join two or more development histories together
一、Merge 這個指令,也就是用來合併開發紀錄用的。首先,我們舉一個例子,現在基於 master 分支,我們額外建立了兩個分支,名稱分別是 apple 及 banana,在 apple 分支裡頭,有一個名為 apple.html 的檔案,同樣的在 banana 分支裡,建立了 banana.html 這個檔案。(目前兩個檔案都沒有任何內容)
這時候,如果我在 apple 分支,執行了 git merge banana
會發生什麼事情?首先 GIT 會詢問你要為這次的合併寫些什麼註解。
撰寫完畢後,就會發現,apple 這個分支裡,出現了 banana.html 這個檔案。
查看 GIT 的圖形也可以發現,目前在 apple 這個分支,增加了一個合併 banana 分支的紀錄。
那 banana 分支呢?它依然還指在原本圖片中 959748a
的那個 commit 上面,並不會因為在 apple 分支 merge 了 banana 分支,而消失。可以想像,我只是把你的手冊,和我不一樣的地方「抄過來」。
所以這時候如果透過 git checkout banana
到 banana 分支,可以發現,是沒有 apple.html 的。
這時候如果在 banana 分支上,持續的編輯 banana.html,並且 commit,也是可以持續的使用 banana 分支,並且 commit 後,banana 分支也會持續的往新的 commit 指向。
第一個例子中,在不同的分支,新增不一樣的兩個檔案,合併的時候,自然出現另一個分支的檔案,還算好理解,但如果是兩個分支都撰寫了同一個檔案呢?以下的例子,我們同樣有 apple 及 banana 兩個分支。
同時編輯 fruit.txt 這個檔案,在 apple 分支上,分別新增兩行文字。
同樣的在 banana 分支上,也新增兩行文字。
git merge banana
會出現什麼事情?首先和第一個例子一樣的,同樣有一個紀錄合併的 commit 出現。
而 fruit.txt 的內容,的確也出現的兩行 banana 分支所加入的文字。
這個例子想表達什麼?所謂的 merge 如同第一個例子提到的,git merge
,只是把你的手冊,和我不一樣的地方「抄過來」,而抄的這個動作,就紀錄在因為合併而產生的那個 commit。
三、以樂高來說 Merge
如上一個例子,假設我們提供了一個底板作為基礎版本,我們叫它 master。
A 版本基於這個底板,分別有兩個步驟,在底板的左邊先增加了粉紅色的積木,而後增加了蘋果綠的積木。
B 版本同樣基於底板,也同樣有兩個步驟,在右邊增加了綠色的積木,而後增加了黑色的積木。
這時候 A 版本 Merge B 版本,其實就是把 B 版本基於「底板」不一樣的地方,在 A 版本上,再實作一次,只是會出現一個「把 B 版本的內容再實作一次」的紀錄在手冊上。
Merge 的概念,就像是「把別的分支和我不一樣的地方,整組抄過來一次」,只是那個抄的過程,都直接紀錄在合併的那個 commit 上了。
對於 GIT 來說,每個 commit 都是基於上一個步驟,紀錄變化,而 merge,也就是從兩個分支的共同起源開始(上面的例子就是基板),把你做的每個步驟的變化內容,在我這邊,再次的實現一次。
之後開始,會提到更多 GIT 合併及重組變化的指令,因此「每個 commit 都是記錄基於上一個 commit 而做的改變」,這個概念我覺得非常的重要。